﻿using System;
using System.Collections.Generic;
using System.IO;
using System.Linq;
using System.Net;
using System.Net.Http;
using System.Net.Http.Formatting;
using System.Net.Http.Headers;
using System.Threading.Tasks;

namespace PivotWebsite.MediaFormatters
{
    public class ImageFormatter : MediaTypeFormatter
    {
        public class BinaryImage
        {
            public byte[] data;
            public string metaData;
        }

        public ImageFormatter()
        {
            SupportedMediaTypes.Add(new MediaTypeHeaderValue("image/jpg"));
            SupportedMediaTypes.Add(new MediaTypeHeaderValue("image/jpeg"));
            SupportedMediaTypes.Add(new MediaTypeHeaderValue("image/png"));
        }

        /// <summary>
        /// We parse a binary image.
        /// </summary>
        /// <param name="type"></param>
        /// <returns></returns>
        public override bool CanReadType(Type type)
        {
            return (type == typeof(BinaryImage));
        }

        /// <summary>
        /// Write out the image as well
        /// </summary>
        /// <param name="type"></param>
        /// <returns></returns>
        public override bool CanWriteType(Type type)
        {
            return (type == typeof(BinaryImage));
        }

        /// <summary>
        /// Read the binary data into our memory for writing out to a file a little later.
        /// </summary>
        /// <param name="type"></param>
        /// <param name="readStream"></param>
        /// <param name="content"></param>
        /// <param name="formatterLogger"></param>
        /// <returns></returns>
        public override async Task<object> ReadFromStreamAsync(Type type, Stream readStream, HttpContent content, IFormatterLogger formatterLogger)
        {
            var b = new BinaryImage();
            b.data = new byte[readStream.Length];

            IEnumerable<string> ctHeaders;
            content.Headers.TryGetValues("Content-Type", out ctHeaders);
            b.metaData = ctHeaders.FirstOrDefault();
            if (b.metaData != null)
                b.metaData = b.metaData.Substring(6);

            var dataRead = await readStream.ReadAsync(b.data, 0, b.data.Length);

            return b;
        }

        /// <summary>
        /// Write the image back to a stream.
        /// </summary>
        /// <param name="type"></param>
        /// <param name="value"></param>
        /// <param name="writeStream"></param>
        /// <param name="content"></param>
        /// <param name="transportContext"></param>
        /// <returns></returns>
        public override async Task WriteToStreamAsync(Type type, object value, Stream writeStream, HttpContent content, TransportContext transportContext)
        {
            var b = value as BinaryImage;
            if (b == null)
                throw new InvalidOperationException("Can only work with BinaryImage types!");

            content.Headers.ContentType = new MediaTypeHeaderValue(string.Format("image/{0}", b.metaData));

            await writeStream.WriteAsync(b.data, 0, b.data.Length);
        }
    }
}